package com.ruoyi.framework.web.service;

import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
import com.ruoyi.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户验证处理
 *
 * @author ruoyi
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);

    private static final String SYS_MANAGER = "system-manager";
    private static final String PROVINCE_MANAGER = "province-manager";
    private static final String CITY_MANAGER = "city-manager";
    private static final String COUNTY_MANAGER = "county-manager";

    @Autowired
    private ISysUserService userService;

    @Autowired
    private SysPasswordService passwordService;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private RedisCache redisCache;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //获取用户类型
        Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext();
        String password = usernamePasswordAuthenticationToken.getCredentials().toString();
        String cacheObject = redisCache.getCacheObject(username + password);
        if (StringUtils.isEmpty(cacheObject)){
            throw new ServiceException("请选择用户类型");
        }
        SysUser user = userService.selectUserByUserName(username,cacheObject);
        if (StringUtils.isNull(user)) {
            log.info("登录用户：{} 不存在.", username);
            throw new ServiceException("登录用户：" + username + " 不存在");
        } else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
            log.info("登录用户：{} 已被删除.", username);
            throw new ServiceException("对不起，您的账号：" + username + " 已被删除");
        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            log.info("登录用户：{} 已被停用.", username);
            throw new ServiceException("对不起，您的账号：" + username + " 已停用");
        }
        passwordService.validate(user);
        return createLoginUser(user);
    }

    public UserDetails createLoginUser(SysUser user) {
        String adcode = user.getRegionCode();
        Integer regionLevel = user.getRegionLevel();
        List<SysRole> sysRoles = user.getRoles();
        List<SysDept> sysDepts = user.getDepts();
        String userType = user.getUserType();
        if ("00".equals(userType) && StringUtils.isEmpty(adcode)) {
            throw new ServiceException("该用户还没配置行政区，无法登录");
        }
        if (sysRoles.isEmpty()) {
            throw new ServiceException("该用户还没配置角色，无法登录");
        }
        //是系统用户，不是管理员用户，处室为空不能登陆
        if ("00".equals(userType) && sysDepts.isEmpty()) {
            if(!sysRoles.stream().anyMatch(role -> "admin".equalsIgnoreCase(role.getRoleKey())
                    || "manager".equalsIgnoreCase(role.getRoleKey()))){
                throw new ServiceException("该用户还没配置处室，无法登录");
            }
        }
        Integer isAdmin = 0;
        //存储处室标识
        List<String> csbsList = new ArrayList<>();
        //获取角色标识
        List<String> roleKeyList = sysRoles.stream().map(item -> item.getRoleKey()).collect(Collectors.toList());
        //判断是超级管理员
        if (roleKeyList.contains("admin") || roleKeyList.contains("ADMIN")) {
            csbsList.add(SYS_MANAGER);
            isAdmin = 1;
        }
        //判断是管理员
        if ("00".equals(userType) && (roleKeyList.contains("manager") || roleKeyList.contains("MANAGER"))) {
            String csbs = "";
            //根据行政区划等级判断省、市、县管理员
            switch (regionLevel) {
                case 1:
                    //省
                    csbs = PROVINCE_MANAGER;
                    break;
                case 2:
                    //市
                    csbs = CITY_MANAGER;
                    break;
                case 3:
                    //县
                    csbs = COUNTY_MANAGER;
                    break;
            }
            csbsList.add(csbs);
        }
        //获取处室标识
        sysDepts.stream().forEach(item -> csbsList.add(item.getDeptCode()));
        //获取角色id
        List<Long> roleIds = sysRoles.stream().map(item -> item.getRoleId()).collect(Collectors.toList());
        //获取部门（处室）id
        List<Long> deptIds = sysDepts.stream().map(item -> item.getDeptId()).collect(Collectors.toList());
        String csbsAll = String.join(",", csbsList);
        user.setRoleIds(roleIds.toArray(new Long[roleIds.size()]));
        user.setDeptIds(deptIds.toArray(new Long[deptIds.size()]));
        return new LoginUser(
                user.getUserId(),
                user.getDeptId(),
                user.getRegionId(),
                user,
                permissionService.getMenuPermission(user),
                adcode,
                regionLevel,
                roleIds,
                null,
                isAdmin,
                csbsAll,
                deptIds);
    }
}
